/*
 * context.cpp
 *
 *  Created on: 2024年6月6日
 *      Author: liangjp
 */
#include <algorithm>
#include <vector>
#include <string.h>
#include <system/Mutex.h>
#include "can/context.h"
#include "utils/BrightnessHelper.h"
#include "utils/Log.h"
#include "common.h"

#include "can/socket_can.h"
#include "base/log.hpp"
#include <iomanip>       // 用于std::setw和std::setfill
#include <sstream>       // 用于字符串流
#include <unordered_map>
#include "base/log.hpp"


typedef struct {
    V_Condition Condition;               // ACC挡位信息
    char versionBuffer[8] = {0};         // 储存版本号字符串
    Vehicle_info1 VehicleInfo1;          // 车身信息1
    Vehicle_info2 VehicleInfo2;
    Vehicle_info3 VehicleInfo3;

    Vehicle_ODO VehicleODO;
    Vehicle_Subtotal VehicleSubtotal;
    Fault_Indicator FaultIndicator;      // 故障指示灯
    SubtotalA subtotalA;
    SubtotalB subtotalB;

    EngineTime engineTime;
    Tire_PressureFault TireFault;
    Tire_Pressure TirePressure;          // 轮胎胎压
    TrailerInformation trailerInfo;      // 拖车信息
    Assisted_Driving assistedDriving;    // 辅助驾驶

    FaultPrompt faultPrompt;             // 故障提示
    RadarInformation radarInfo;          // 雷达
    UnitStatus unitStatus;               // 单位
    Time_Synchronization_Info TimeSync;  // 时间同步信息
    key_value_t keyValue;                // 控制按键

    wchar_t mediaBuffer[31] = L"";       // 最大15个字符，每个字符2字节，加结束符
} DashboardData;
namespace can {

// 将两个字节组合成一个16位的值（低字节在前，高字节在后）
#define MAKEWORD(low, high)    (((uint16_t)(low)) | (((uint16_t)(high)) << 8))

// 将四个字节组合成一个32位的值（低字节在前，高字节在后）
#define MAKELONG(l_low, l_high, h_low, h_high) \
    ((uint32_t(MAKEWORD(l_low, l_high))) | (uint32_t(MAKEWORD(h_low, h_high)) << 16))

// 将三个字节组合成一个24位的值（低字节在前，高字节在后）
#define MAKE24BIT(b0, b1, b2) \
    ((uint32_t(b0)) | ((uint32_t(b1)) << 8) | ((uint32_t(b2)) << 16))

// 回调函数集合
static std::set<CanDataCb *> _s_cb_set;
static Mutex _s_cb_mutex;

// 定义新的宏，它直接使用固定的集合和类型
#define CB_FOREACH_CAN(cb, arg) \
	Mutex::Autolock _l(_s_cb_mutex);	\
    for (std::set<CanDataCb*>::iterator it = _s_cb_set.begin(); it != _s_cb_set.end(); ++it) { \
        if ((*it)->cb) { \
            (*it)->cb(arg); \
        } \
    }

typedef struct {
	uint32_t canId;
	void (*proc)(can_frame& can);
} ProcFun;


void printCanData(const can_frame& can) {
    std::stringstream ss;
    ss << std::hex << std::uppercase; // 设置为16进制并使用大写字母
    for (size_t i = 0; i < can.can_dlc; ++i) {
        // 将每个字节转换成16进制字符串并存储到字符串流中
        ss << std::setw(2) << std::setfill('0')
           << static_cast<int>(can.data[i]) << ' ';
    }
    // 使用LOGI_TRACE打印整个字符串
    LOGI_TRACE("%s", ss.str().c_str());
}


// 添加回调函数
void add_cb(CanDataCb *cb) {
	Mutex::Autolock _l(_s_cb_mutex);
	_s_cb_set.insert(cb);
}

void remove_cb(CanDataCb *cb) {
	Mutex::Autolock _l(_s_cb_mutex);
	auto it = _s_cb_set.find(cb);
	if(it != _s_cb_set.end()){
		_s_cb_set.erase(cb);
	}
}


void startup(){
	SOCKETCAN->startup();
}

void canSend(uint32_t can_id, uint8_t dlc, uint8_t * data){
	SOCKETCAN->write(can_id, dlc, data);
}

static DashboardData sDashboardData;
//返回最新的can广播数据
//DashboardData getDashboardData(){
//	return sDashboardData;
//}



//解析车身状态
static void procVehicleCond(can_frame& can){

	sDashboardData.Condition.ACC.byte = can.data[0];
	sDashboardData.Condition.gear = can.data[1];
	sDashboardData.Condition.gearGrade = can.data[2];
	sDashboardData.Condition.gearRank = can.data[3];
	sDashboardData.Condition.CumulativeFuel = MAKEWORD(can.data[4] , can.data[5]);
	sDashboardData.Condition.compass = can.data[6];
	sDashboardData.Condition.Hanging = can.data[7];
	// 调用 V_CONDITION 的所有回调函数
	CB_FOREACH_CAN(condition_cb,sDashboardData.Condition);
}

static void procVehicleInfo1(can_frame& can){
	sDashboardData.VehicleInfo1.rotation_ = MAKEWORD(can.data[2],can.data[3]);
	sDashboardData.VehicleInfo1.speed_ = MAKEWORD(can.data[0],can.data[1]);
	sDashboardData.VehicleInfo1.tyreDirection = can.data[7];
	sDashboardData.VehicleInfo1.tyreAngle = can.data[6];
	sDashboardData.VehicleInfo1.Instant_fuel_consumption = MAKEWORD(can.data[4],can.data[5]);

	CB_FOREACH_CAN(vehicle_info1_cb, sDashboardData.VehicleInfo1);
}
static void procVehicleInfo2(can_frame& can){
	sDashboardData.VehicleInfo2.CoolantTemperature = MAKEWORD(can.data[0],can.data[1]);
	sDashboardData.VehicleInfo2.Display_Mode = can.data[3];
	sDashboardData.VehicleInfo2.Oil_percentage = can.data[2];
	sDashboardData.VehicleInfo2.RangeEndurance = MAKEWORD(can.data[4],can.data[5]);
	sDashboardData.VehicleInfo2.TransmissionTemp = MAKEWORD(can.data[6],can.data[7]) ;

	CB_FOREACH_CAN(vehicle_info2_cb, sDashboardData.VehicleInfo2);
}
static void procVehicleInfo3(can_frame& can){
	sDashboardData.VehicleInfo3.OutdoorTemp = MAKEWORD(can.data[0],can.data[1]) ;
	sDashboardData.VehicleInfo3.EngineOilTemp = MAKEWORD(can.data[2],can.data[3]) ;
	sDashboardData.VehicleInfo3.OilPressure = MAKEWORD(can.data[4],can.data[5]);
	sDashboardData.VehicleInfo3.BatteryVoltage = MAKEWORD(can.data[4],can.data[5]) / 10;

	CB_FOREACH_CAN(vehicle_info3_cb, sDashboardData.VehicleInfo3);
}

static void procFaultInd(can_frame& can){
	sDashboardData.FaultIndicator.fault0.byte = can.data[0];
	sDashboardData.FaultIndicator.fault1.byte = can.data[1];
	sDashboardData.FaultIndicator.fault2.byte = can.data[2];
	sDashboardData.FaultIndicator.fault3.byte = can.data[3];
	sDashboardData.FaultIndicator.fault4.byte = can.data[4];
	sDashboardData.FaultIndicator.fault5.byte = can.data[5];

	CB_FOREACH_CAN(fault_indicator_cb, sDashboardData.FaultIndicator);
}
static void procKeyValue(can_frame& can){
	sDashboardData.keyValue.pre_status = sDashboardData.keyValue.status;	//上一个的按键状态
	sDashboardData.keyValue.status = (key_status)(can.data[0]);

	if(sDashboardData.keyValue.status){
		//只有当前按键值有效才保存
		sDashboardData.keyValue.operation = (key_operation_e)(can.data[1]);
	}

	CB_FOREACH_CAN(key_value_cb, sDashboardData.keyValue);
}

static void procTimeSync(can_frame& can){
	sDashboardData.TimeSync.Hour = can.data[0];
	sDashboardData.TimeSync.Minute = can.data[1];

	CB_FOREACH_CAN(time_sync_info_cb, sDashboardData.TimeSync);
}

static void procVehicleodo(can_frame& can){
	sDashboardData.VehicleODO.odo = MAKELONG(can.data[0],can.data[1],can.data[2],can.data[3]);
	sDashboardData.VehicleODO.oilLife = can.data[4];
	sDashboardData.VehicleODO.SubtotalMileage = MAKEWORD(can.data[5], can.data[6]);

	CB_FOREACH_CAN(vehicle_odo_cb, sDashboardData.VehicleODO);
}
static void procVehicleSub(can_frame& can){
	sDashboardData.VehicleSubtotal.SubtotalMileageA = MAKELONG(can.data[0],can.data[1],can.data[2],can.data[3]);
	sDashboardData.VehicleSubtotal.SubtotalMileageB = MAKELONG(can.data[4],can.data[5],can.data[6],can.data[7]);
	CB_FOREACH_CAN(vehicle_subtotal_cb, sDashboardData.VehicleSubtotal);
}
static void procSubA(can_frame& can){
	sDashboardData.subtotalA.AverageFuel = MAKEWORD(can.data[0], can.data[1]) / 10;
	sDashboardData.subtotalA.TravelTime = MAKE24BIT(can.data[2], can.data[3],can.data[4]);
	sDashboardData.subtotalA.AverageVelocity = MAKEWORD(can.data[5], can.data[6]) / 10;
	CB_FOREACH_CAN(SubtotalA_cb, sDashboardData.subtotalA);
}
static void procSubB(can_frame& can){
	sDashboardData.subtotalB.AverageFuel = MAKEWORD(can.data[0], can.data[1]) / 10;
	sDashboardData.subtotalB.TravelTime = MAKE24BIT(can.data[2], can.data[3],can.data[4]);
	sDashboardData.subtotalB.AverageVelocity = MAKEWORD(can.data[5], can.data[6]) / 10;
	CB_FOREACH_CAN(SubtotalB_cb, sDashboardData.subtotalB);
}
static void procEngine(can_frame& can){
	sDashboardData.engineTime.freeTime = MAKEWORD(can.data[0], can.data[1]);
	sDashboardData.engineTime.RunningTime = MAKEWORD(can.data[2], can.data[3]);
	sDashboardData.engineTime.TotalTime = MAKEWORD(can.data[4], can.data[5]);
	CB_FOREACH_CAN(EngineTime_cb, sDashboardData.engineTime);
}
static void procTtire1(can_frame& can){
	sDashboardData.TireFault.vehicleType = can.data[0] & 0x03;
	sDashboardData.TireFault.TireFault.byte = can.data[0];
	sDashboardData.TireFault.RL_InnerSide = MAKEWORD(can.data[1], can.data[2]);
	sDashboardData.TireFault.RR_InnerSide = MAKEWORD(can.data[3], can.data[4]);
	CB_FOREACH_CAN(time_sync_info_cb, sDashboardData.TimeSync);
}
static void procTire2(can_frame& can){
	sDashboardData.TirePressure.FL_TP =  MAKEWORD(can.data[0], can.data[1]);
	sDashboardData.TirePressure.FR_TP =  MAKEWORD(can.data[2], can.data[3]);
	sDashboardData.TirePressure.RL_TP =  MAKEWORD(can.data[4], can.data[5]);
	sDashboardData.TirePressure.RR_TP =  MAKEWORD(can.data[6], can.data[7]);

	CB_FOREACH_CAN(tire_pressure_cb, sDashboardData.TirePressure);
}
static void proctrailer(can_frame& can){
	sDashboardData.trailerInfo.TrailerStatus = can.data[0];
	sDashboardData.trailerInfo.Gain = can.data[1] / 10;
	sDashboardData.trailerInfo.AntiTrailer = can.data[2];
	sDashboardData.trailerInfo.TrailerDistance = MAKE24BIT(can.data[3], can.data[4],can.data[5]);

	CB_FOREACH_CAN(TrailerInformation_cb, sDashboardData.trailerInfo);
}
static void procradarInfo(can_frame& can){
	sDashboardData.radarInfo.FL_Radar = can.data[0] & 0x0F;
	sDashboardData.radarInfo.FL_RadarM = can.data[1] & 0x0F;
	sDashboardData.radarInfo.FR_Radar = can.data[3] & 0x0F;
	sDashboardData.radarInfo.FR_RadarM = can.data[2] & 0x0F;
	sDashboardData.radarInfo.RL_Radar = can.data[4] & 0x0F;
	sDashboardData.radarInfo.RL_RadarM = can.data[5] & 0x0F;
	sDashboardData.radarInfo.RR_Radar = can.data[7] & 0x0F;
	sDashboardData.radarInfo.RR_RadarM = can.data[6] & 0x0F;
	sDashboardData.radarInfo.FL_Radar_blink = (can.data[0] & 0xF0) >> 4;
	sDashboardData.radarInfo.FL_RadarM_blink = (can.data[1] & 0xF0) >> 4;
	sDashboardData.radarInfo.FR_Radar_blink = (can.data[2] & 0xF0) >> 4;
	sDashboardData.radarInfo.FR_RadarM_blink = (can.data[3] & 0xF0) >> 4;
	sDashboardData.radarInfo.RL_Radar_blink = (can.data[4] & 0xF0) >> 4;
	sDashboardData.radarInfo.RL_RadarM_blink = (can.data[5] & 0xF0) >> 4;
	sDashboardData.radarInfo.RR_Radar_blink = (can.data[6] & 0xF0) >> 4;
	sDashboardData.radarInfo.RR_RadarM_blink = (can.data[7] & 0xF0) >> 4;

	CB_FOREACH_CAN(RadarInformation_cb, sDashboardData.radarInfo);
}
static void procUint(can_frame& can){
	sDashboardData.unitStatus.s_temperature = (UNIT_T)can.data[0];
	sDashboardData.unitStatus.s_speed = (UNIT_S)can.data[1];
	sDashboardData.unitStatus.s_distance = (UNIT_D)can.data[2];
	sDashboardData.unitStatus.s_fuel = (UNIT_O)can.data[3];
	sDashboardData.unitStatus.s_pressure = (UNIT_P)can.data[4];

	CB_FOREACH_CAN(UnitStatus_cb, sDashboardData.unitStatus);
}

//解析版本号
static void procVerInfo(can_frame& can){

    // 复制数据到 versionBuffer
    for (int i = 0; i < 8 ; ++i) {
        sDashboardData.versionBuffer[i] = can.data[i];
    }
    CB_FOREACH_CAN(version_info_cb, sDashboardData.versionBuffer);
}
static void procMedia(can_frame& can) {
    static int currentFrameIndex = 0;  // 当前帧序号
    static bool isLastFrame = false;   // 是否为最后一帧
    static size_t totalLength = 0;        // 已接收的数据总长度

    // 提取帧序号和是否是最后一帧的信息
    uint8_t frameIndex = can.data[0];
    isLastFrame = (can.data[1] == 0x00);

    // 检查帧序号是否正确
    if (frameIndex != currentFrameIndex || (isLastFrame && frameIndex != 0)) {
        // 如果帧序号不匹配或非第一帧却为最后一帧，重置状态
        currentFrameIndex = 0;
        totalLength = 0;
        memset(sDashboardData.mediaBuffer, 0, sizeof(sDashboardData.mediaBuffer));
        return;
    }

    // 解析并复制数据到 sDashboardData.mediaBuffer
    for (size_t i = 0; i < 3 && totalLength + 1 < sizeof(sDashboardData.mediaBuffer) / sizeof(wchar_t); ++i) {
        uint16_t unicodeChar = (can.data[2 * i + 2] << 8) | can.data[2 * i + 3]; // 组合两个字节为一个Unicode字符
        if (unicodeChar == 0x0000) {
            // 遇到空字符，停止复制
            break;
        }
        sDashboardData.mediaBuffer[totalLength++] = static_cast<wchar_t>(unicodeChar);
    }
    // 更新当前帧序号
    currentFrameIndex++;

    // 检查是否接收到最后一帧
    if (isLastFrame) {
        // 所有帧都已接收完毕
        sDashboardData.mediaBuffer[totalLength] = L'\0';  // 确保宽字符串以null终止
        currentFrameIndex = 0;            // 重置帧序号
        totalLength = 0;                  // 重置总长度

        // 将宽字符数组转换为多字节字符串（假设系统使用UTF-8编码）
        char mbString[64] = "";
        #ifdef _WIN32
        WideCharToMultiByte(CP_UTF8, 0, sDashboardData.mediaBuffer, -1, mbString, sizeof(mbString), NULL, NULL);
        #else
        // 在Linux和其他平台上，可以使用iconv或其他方法转换
        // 这里简化处理，直接用wchar_t转char，实际应用中应考虑正确的转换方法
        mbString[0] = '\0';
        for (size_t i = 0; i < wcslen(sDashboardData.mediaBuffer); ++i) {
            // 这里只是简单地将wchar_t转换为char，实际应用中应该使用适当的转换函数
            strncat(mbString, reinterpret_cast<char*>(&sDashboardData.mediaBuffer[i]), 1);
        }
        #endif

        CB_FOREACH_CAN(media_info_cb, mbString);
    }
}
static void procAssisted(can_frame& can){
	sDashboardData.assistedDriving.AssistedType = can.data[0];
	sDashboardData.assistedDriving.DistanceCar = can.data[1];
	sDashboardData.assistedDriving.isCar = can.data[2] & 0x0F;
	sDashboardData.assistedDriving.twinkle = (can.data[2] & 0xF0) >> 4;
	sDashboardData.assistedDriving.AssisedSpeed = MAKEWORD(can.data[3], can.data[4]);

	CB_FOREACH_CAN(Assisted_Driving_cb, sDashboardData.assistedDriving);
}
static void procfaultPrompt(can_frame& can){
	sDashboardData.faultPrompt.AddOrDel = MAKEWORD(can.data[1], can.data[2]);
	sDashboardData.faultPrompt.FaultID = MAKEWORD(can.data[4], can.data[5]);

	CB_FOREACH_CAN(FaultPrompt_cb, sDashboardData.faultPrompt);
}
// 指令解析表
static ProcFun _s_proc_fun_tab[] = {
		0x1FFF0056, procVehicleCond,
		0x1FFF006C, procVerInfo,
		0x1FFF0050, procVehicleInfo1,
		0x1FFF0052, procVehicleInfo2,
		0x1FFF0054, procVehicleInfo3,

		0x1FFF0058, procVehicleodo,
		0x1FFF005A, procVehicleSub,
		0x1FFF0010, procFaultInd,
		0x1FFF0030,	procKeyValue,
		0x1FFF0062,	procTtire1,

		0x1FFF0064,	procTire2,
		0x1FFF005C,	procSubA,
		0x1FFF005E,	procSubB,
		0x1FFF006E,	procTimeSync,
		0x1FFF0060,	procEngine,

		0x1FFF0066,	proctrailer,
		0x1FFF0068,	procradarInfo,
		0x1FFF006A,	procUint,
		0x1FFF0070,	procMedia,
		0x1FFF0090,	procAssisted,

		0x1FFF00A0,	procfaultPrompt,
};

/**
 * 解析每一帧数据
 */
static void procParse(const can_frame& canFrame)
{
	can_frame sCanFrameData;

	sCanFrameData.can_id = canFrame.can_id & 0x1FFFFFFF;

//	LOGD_TRACE("[can][read]can_id:0x%X", sCanFrameData.can_id);
	sCanFrameData.can_dlc = canFrame.can_dlc;
	memcpy(sCanFrameData.data, canFrame.data, canFrame.can_dlc);
//	memcmp(sCanFrameData.data, canFrame.data, canFrame.can_dlc);

	for(uint32_t i = 0; i < TAB_SIZE(_s_proc_fun_tab); i++){
		if(sCanFrameData.can_id == _s_proc_fun_tab[i].canId){
			_s_proc_fun_tab[i].proc(sCanFrameData);
		}
	}


}

/**
 * 功能：解析协议
 * 参数：pData 协议数据，len 数据长度
 */
void parseProtocol(const can_frame& canFrame)
{
//	printCanData(canFrame);
	procParse(canFrame);
}







}

